/*
function defineProperty(target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;
function getOwnPropertyDescriptor(target: object, propertyKey: PropertyKey): PropertyDescriptor | undefined;

function ownKeys(target: object): PropertyKey[];

function set(target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
function get(target: object, propertyKey: PropertyKey, receiver?: any): any;
function has(target: object, propertyKey: PropertyKey): boolean;
function deleteProperty(target: object, propertyKey: PropertyKey): boolean;
function preventExtensions(target: object): boolean;
function isExtensible(target: object): boolean;
function construct(target: Function, argumentsList: ArrayLike<any>, newTarget?: any): any;

function setPrototypeOf(target: object, proto: any): boolean;
function getPrototypeOf(target: object): object;

function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;
*/

/** 1. function set(target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean */
const obj = {};
// obj.name = 'ahhh';
console.log(Reflect.set(obj, 'name', 'ahhh')); //true

/** 2. function get(target: object, propertyKey: PropertyKey, receiver?: any): any;*/
/**
 * Gets the property of target, equivalent to `target[propertyKey]` when `receiver === target`.
 * @param target Object that contains the property on itself or in its prototype chain.
 * @param propertyKey The property name.
 * @param receiver The reference to use as the `this` value in the getter function,
 *        if `target[propertyKey]` is an accessor property.
 */
// obj[name]
console.log(Reflect.get(obj, 'name')); //'ahhh'


/** 3. function has(target: object, propertyKey: PropertyKey): boolean */
console.log('a' in {a:1}); //true
console.log(Reflect.has({a:1},'a')); //true

/** 4. function deleteProperty(target: object, propertyKey: PropertyKey): boolean */
const obj2 = {a: 1, b: 2};
// delete obj2.a
console.log(Reflect.deleteProperty(obj2, 'a')); //true
console.log(obj2) //{ b: 2 }

/** 5. function preventExtensions(target: object): boolean */
/** 6. function isExtensible(target: object): boolean */
const obj3 = {a: 1};
console.log(Reflect.isExtensible(obj3)); //true
console.log(Reflect.preventExtensions(obj3)); //true
obj3.b = 222;
console.log(obj3); //{ a: 1 }
console.log(Reflect.isExtensible(obj3)); //false

/** 7. function construct(target: Function, argumentsList: ArrayLike<any>, newTarget?: any): any */
class XXX{
  constructor(name){
    this.name = name
  }
}
const xxx =  Reflect.construct(XXX,['ahhh']);
console.log(xxx); // XXX { name: 'ahhh' }


/** 8. function setPrototypeOf(target: object, proto: any): boolean */
function Animal(){}
Animal.prototype.a1 = 'a1';
function Tiger(){}

//Tiger.prototype.__proto__ = Animal.prototype;
//↕等价
//Object.setPrototypeOf(Tiger.prototype, Animal.prototype);
//↕等价
Reflect.setPrototypeOf(Tiger.prototype, Animal.prototype)

console.log(new Tiger().a1);  //a1

/** 9. function getPrototypeOf(target: object): object */
//Object.getPrototypeOf()
console.log(Reflect.getPrototypeOf(new Tiger())===Tiger.prototype); //true


/** 10. function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any*/
const fn = function(a,b){
  console.log(this,a,b);
}
fn.apply = function(){
  console.log('diy')
}
fn.apply(); //diy //走的是我们自己定义的apply方法
//想调原生apply 怎么调？
console.log(fn.__proto__ === Function.prototype); //true
console.log(fn.__proto__.apply === Function.prototype.apply); //true

//↓的call会让apply方法中的this指向fn(即fn调apply) 也就等价于 fn.apply({a:1},[2,3])
Function.prototype.apply.call(fn, {a:1},[2,3]); //{ a: 1 } 2 3
//↕ 等价
Reflect.apply(fn, {a:1},[2,3]); //{ a: 1 } 2 3
